package com.cxf.windex.base.util;

import com.alibaba.fastjson.JSON;
import com.cxf.windex.entity.vo.WxPayInfo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * @author chenxf
 * @date 3/16/2018
 * @description
 */
public class WxUtil {
  private static RestTemplate restTemplate = new RestTemplate();

  public static final org.slf4j.Logger logger = LoggerFactory.getLogger(WxUtil.class);

  private  static String wxUrl="https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
  private static String wxTokenUrl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
  private static String wxDownloadUrl="http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";
  private static String wxOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

  private static String minaCodeUrl="https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN";
  private static String minaCodeUrlB="https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN";

  private static String timeformat = "yyyyMMddHHmmss";
  private static int timeexpire = 1;

  private static String appKey = "junengzhongchuanlk100624xingfen2";



  /**
   * 统一下单接口
   * @param openId openid
   * @param clientIP 客户端IP
   * @param randomNonceStr 随机数
   * @param appid appid
   * @param mchid 商户号
   * @param notifyUrl 回调地址
   * @param appKey 商户密钥
   */
  public static String unifiedOrder(String openId, String clientIP, String randomNonceStr,
      String appid, String mchid, String notifyUrl, String appKey) {
    try {
      WxPayInfo payInfo = new WxPayInfo()
          .createPayInfo(openId, clientIP, randomNonceStr, timeformat, timeexpire, appid, mchid,
              notifyUrl);
      String md5 = getSign(payInfo, appKey);
      payInfo.setSign(md5);

      logger.error("md5 value: " + md5);

      String xml = CommonUtil.payInfoToXML(payInfo);
      xml = xml.replace("__", "_").replace("<![CDATA[1]]>", "1");
      //xml = xml.replace("__", "_").replace("<![CDATA[", "").replace("]]>", "");
      logger.debug("xml={}", xml);
      StringBuffer buffer = HttpUtil.httpsRequest(wxOrderUrl, "POST", xml);

      logger.error("unifiedOrder request return body: \n" + buffer.toString());
      Map<String, String> result = CommonUtil.parseXml(buffer.toString());

      String return_code = result.get("return_code");
      if (StringUtils.isNotBlank(return_code) && return_code.equals("SUCCESS")) {

        String return_msg = result.get("return_msg");
        if (StringUtils.isNotBlank(return_msg) && !return_msg.equals("OK")) {
          return "";
        }

        String prepay_Id = result.get("prepay_id");
        return prepay_Id;

      } else {
        return "";
      }

    } catch (Exception e) {
      e.printStackTrace();
    }

    return "";
  }
  /**
   * 获取微信openid
   * @param appid appid
   * @param secret secret
   * @param jscode jscode
   * @return
   *   err:  {"errcode":40013,"errmsg":"invalid appid, hints: [ req_id: 0PFNQa0729th42 ]"}
   *   success:{"session_key":"R+AJs7g+f5841HSn51W0bA==","openid":"oLw0k0Ss_Ntjj-o5KT13L8PcXbsU"}
   */
  public static Map<String, String>  getOpenId(String appid,String secret, String jscode){
    String requestUrl =
        wxUrl.replace("APPID", appid).replace("SECRET", secret).replace("JSCODE", jscode);

    String oauth = restTemplate.getForObject(requestUrl, String.class);
    System.out.println("log"+oauth);
    try {
       return (Map<String, String>)JSON.parseObject(oauth,Map.class);

    } catch (Exception e) {
      e.printStackTrace();
    }

    return null;
  }

  public static String getWxToken(String appid,String secret) {
    String requestUrl =
        wxTokenUrl.replace("APPID", appid).replace("SECRET", secret);

    String oauth = restTemplate.getForObject(requestUrl, String.class);
    System.out.println("log"+oauth);
    try {
      return ((Map<String, String>)JSON.parseObject(oauth,Map.class)).get("access_token");

    } catch (Exception e) {
      e.printStackTrace();
    }

    return null;
  }

  /**
   * 获取媒体文件
   * @param appid appid
   * @param secret secret
   * @param mediaId 媒体文件id
   * @param savePath 文件在本地服务器上的存储路径

   * */
  public static String downloadMedia(String appid,String secret,String mediaId, String savePath) {

    String accessToken = getWxToken(appid,secret);
    System.out.println(":" + accessToken);
    String filePath = null;
    // 拼接请求地
    String requestUrl = wxDownloadUrl.replace("ACCESS_TOKEN", accessToken).replace("MEDIA_ID", mediaId);
    try {
      URL url = new URL(requestUrl);
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setDoInput(true);
      conn.setRequestMethod("GET");
      File path = new File(savePath);
      if (!path.exists()) {
        path.mkdirs();
      }
      if (!savePath.endsWith("/")) {
        savePath += "/";
      }

      // 根据内容类型获取扩展名
      String fileExt = getFileexpandedName(conn.getHeaderField("Content-Type"));
      // 将mediaId作为文件名
      filePath = savePath + mediaId + fileExt;
      BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
      FileOutputStream fos = new FileOutputStream(new File(filePath));
      byte[] buf = new byte[8096];
      int size = 0;
      while ((size = bis.read(buf)) != -1) {
        fos.write(buf, 0, size);
      }
      fos.close();
      bis.close();

      conn.disconnect();
      String info = String.format("下载媒体文件成功，filePath=" + filePath);

      return mediaId + fileExt;
    } catch (Exception e) {
      filePath = null;
      String error = String.format("下载媒体文件失败：%s", e);
      System.out.println(error);
    }
    return mediaId;
  }

  /**
   * 根据内容类型判断文件扩展名
   *
   * @param contentType 内容类型
   * @return
   */
  public static String getFileexpandedName(String contentType) {
    switch (contentType) {
      case "image/jpeg":
        return ".jpg";
      case "audio/mpeg":
        return ".mp3";
      case "audio/amr":
        return ".amr";
      case "video/mp4":
        return ".mp4";
      case "video/mpeg4":
        return ".mp4";
      default:
        return ".jpg";
    }
  }

  private static String getSign(WxPayInfo payInfo, String key) throws Exception {
    StringBuffer sb = new StringBuffer();
    sb.append("appid=" + payInfo.getAppid())
        .append("&attach=" + payInfo.getAttach())
        .append("&body=" + payInfo.getBody())
        .append("&device_info=" + payInfo.getDevice_info())
        .append("&limit_pay=" + payInfo.getLimit_pay())
        .append("&mch_id=" + payInfo.getMch_id())
        .append("&nonce_str=" + payInfo.getNonce_str())
        .append("&notify_url=" + payInfo.getNotify_url())
        .append("&openid=" + payInfo.getOpenid())
        .append("&out_trade_no=" + payInfo.getOut_trade_no())
        .append("&sign_type=" + payInfo.getSign_type())
        .append("&spbill_create_ip=" + payInfo.getSpbill_create_ip())
        .append("&time_expire=" + payInfo.getTime_expire())
        .append("&time_start=" + payInfo.getTime_start())
        .append("&total_fee=" + payInfo.getTotal_fee())
        .append("&trade_type=" + payInfo.getTrade_type())
        .append("&key=" + key);
   logger.debug("url={}",sb.toString());
    return CommonUtil.getMD5(sb.toString().trim()).toUpperCase();
  }

  public static String getMinaSign(String appid ,String timestamp,String nonceStr,String prepayId,String key) throws Exception {
    StringBuffer sb = new StringBuffer();
    sb.append("appdI=" + appid)
        .append("&timeStamp=" + timestamp)
        .append("&nonceStr=" + nonceStr)
        .append("&package=prepay_id=" + prepayId)
        .append("&signType=MD5" )
        .append("&key=" + key);
    logger.debug("url={}",sb.toString());
    return CommonUtil.getMD5(sb.toString().trim()).toUpperCase();
  }

  public static byte[] getMinaCode(String appid,String secret,Map<String,String> param){
    String accessToken = getWxToken(appid,secret);
    String requestUrl =
        minaCodeUrl.replace("ACCESS_TOKEN", accessToken);

    try {
      MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
      HttpEntity requestEntity = new HttpEntity(param, headers);
      ResponseEntity<byte[]> entity = restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
      logger.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());



//      Path path = Paths.get("d:/upload/xcx.jpg");
//      Files.write(path, entity.getBody());
      // postForObject(requestUrl,postStr ,"POST",String.class);
      logger.debug(" result={}",entity.getBody());
      return entity.getBody();

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  public static byte[] getMinaCodeB(String appid,String secret,Map<String,Object> param){
    String accessToken = getWxToken(appid,secret);
    String requestUrl =
        minaCodeUrlB.replace("ACCESS_TOKEN", accessToken);

    try {
      MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
      HttpEntity requestEntity = new HttpEntity(param, headers);
      ResponseEntity<byte[]> entity = restTemplate.exchange(requestUrl, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
     // logger.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());



//      Path path = Paths.get("d:/upload/xcx.jpg");
//      Files.write(path, entity.getBody());
      // postForObject(requestUrl,postStr ,"POST",String.class);
      logger.debug(" result={}",entity.getBody());
      return entity.getBody();

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }


  public static void main(String[] args) {
    Map<String,Object> map=new HashMap<>(2);
    map.put("scene","jsId=428518393122004992");
    map.put("page","pages/index/index");
    byte[] codeBytes= WxUtil.getMinaCodeB("wx3f8cc71cec29b704","8942ea96dc171ffba7bfc3049ff801d8", map);
    logger.debug(new String(codeBytes));
    Path path = Paths.get("d:/upload/xcx.jpg");
    try {
      Files.write(path, codeBytes);
    } catch (IOException e) {
      e.printStackTrace();
    }
//    String prepay_Id = WxUtil.orderPay("opM0P5RXkpmJa3V3Ubjq9Xc-FoSU",
//        "125.111.140.243","wx3f8cc71cec29b704"
//        , "1500459082", "http://tech.junenng-zh.com/login", appKey,0.01,"测试支付",CommonUtil.getRandomOrderId(),RandomUtils.generateMixString(32));

//    String prepay_Id = WxUtil.unifiedOrder("opM0P5RXkpmJa3V3Ubjq9Xc-FoSU",
//        "125.111.140.243",RandomUtils.generateMixString(32),"wx3f8cc71cec29b704"
//        , "1500459082", "http://tech.junenng-zh.com/login",appKey);
//
//    System.out.printf("prepay_Id={}"+ prepay_Id);
    //System.out.println(WxUtil.getWxToken("wx88e51cf7b02246a8","e064ed666445967867309fad51350136"));
    //System.out.println(WxUtil.downloadMedia("wx3f8cc71cec29b704","8942ea96dc171ffba7bfc3049ff801d8","vymh_AhYI_v5R9BrpXi0tyCmIkHFbxOalR_Uyh9y298OuLE0_pWIZ1ikNVaLlgU3","d:/upload"));
   // System.out.println(WxUtil.downloadMedia("wx3f8cc71cec29b704","8942ea96dc171ffba7bfc3049ff801d8","o6zAJs6mR_c9FYoiXIjRO-Q7GF0o.d91901ad340956fccabea5f276c05f8d","d:/upload"));

    //WxUtil.getOpenId("wx3f8cc71cec29b704","8942ea96dc171ffba7bfc3049ff801d8","061PViCl00hnCl1WSbDl0vJmCl0PViCt");
  }
}
